package com.taobao.top.link.remoting;

import java.lang.reflect.Method;
import java.util.HashMap;

import org.springframework.beans.factory.ListableBeanFactory;

public class SpringMethodCallProcessor implements MethodCallProcessor {
  private HashMap<String, Object> services;

  public SpringMethodCallProcessor(ListableBeanFactory beanFactory) {
    this.services = new HashMap<String, Object>();
    this.readServices(beanFactory);
  }

  @Override
  public MethodReturn process(MethodCall methodCall, MethodCallContext callContext) throws Throwable {
    try {
      MethodCallContextBean.setCurrentContext(callContext);
      Object target = services.get(methodCall.TypeName);
      MethodReturn methodReturn = new MethodReturn();
      methodReturn.ReturnValue = this.getMethod(target, methodCall).invoke(target, methodCall.Args);
      return methodReturn;
    } finally {
      MethodCallContextBean.setCurrentContext(null);
    }
  }

  public void register(String serviceInterface, Object serviceObject) {
    this.services.put(serviceInterface, serviceObject);
  }

  private void readServices(ListableBeanFactory beanFactory) {
    String[] names = beanFactory.getBeanNamesForType(ServiceBean.class);
    for (String n : names) {
      ServiceBean s = (ServiceBean) beanFactory.getBean(n);
      this.register(s.getInterfaceName(), s.getTarget());
    }
  }

  private Method getMethod(Object target, MethodCall methodCall) throws SecurityException, NoSuchMethodException {
    try {
      return target.getClass().getMethod(methodCall.MethodName, methodCall.MethodSignature);
    } catch (NoSuchMethodException e) {
      return target.getClass().getMethod(methodCall.MethodName);
    }
  }
}
